﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BobcatMultiTouch;

namespace Sample3_DrawingWithMultipleInputAreas
{
    /// <summary>
    /// This control allows you to draw into it using sources supported by the Bobcat
    /// MultiTouchInputManager (MTIM). It uses the MultiTouchInputClient (MTIC) to raise 
    /// events into this control when "touch-events" (down, up, move) occur.
    /// </summary><remarks>
    /// The MTIM manages the various available sources such as the mouse or wiimote IR 
    /// inputs. The MTIC is useful to get the touch events from the MTIM into a particular
    /// form or control. 
    /// 
    /// Each instance of this control holds its own MTIC. In the control's load event we 
    /// initialize the MTIC, passing in a reference to the control using the 'this' object.
    /// The MTIC will then be managing events for this control. It will only raise events to
    /// us that occur in this control, and it will give us touch-events in coordinates relative
    /// to the client-area of this control.
    /// 
    /// The important part of the sample is really just the control's load event where we 
    /// initialize the MTIC and register for the events. The rest of the code is just drawing code
    /// that you would replace with whateverr code you wanted for your own application.
    /// </remarks>
    public partial class DrawingControl : UserControl
    {
        #region Public methods

        /// <summary>
        /// Constructor.
        /// </summary>
        public DrawingControl()
        {
            InitializeComponent();
        }

        #endregion

        #region Private functions

        /// <summary>
        /// Called when the control is loaded. We initialize the MTIC and register for
        /// events from it.
        /// </summary>
        private void DrawingControl_Load(object sender, EventArgs e)
        {
            m_MTIC.initialize(this);
            m_MTIC.TouchDownEvent += onTouchDown;
            m_MTIC.TouchUpEvent += onTouchUp;
            m_MTIC.TouchMoveEvent += onTouchMove;
        }

        /// <summary>
        /// Called when we receive a touch-down event.
        /// </summary>
        private void onTouchDown(object sender, TouchArgs args)
        {
            // We draw a dot at the touch position...
            Point clientPoint = args.ClientPosition;
            Point destinationPoint = new Point(clientPoint.X + 1, clientPoint.Y);

            // We show it in the correct color for this source...
            Pen pen = getPen(args.PointIndex);
            Graphics g = getGraphics();
            g.DrawLine(pen, clientPoint, destinationPoint);

            // We store this point...
            m_mapPreviousPoints[args.PointIndex] = clientPoint;

        }

        /// <summary>
        /// Called when we receive a touch-up event. 
        /// </summary>
        private void onTouchUp(object sender, TouchArgs args)
        {
            // We remove the previous point entry for this source. (Otherwise we
            // would always draw an unwanted line between different unconnected lines.)
            m_mapPreviousPoints.Remove(args.PointIndex);
        }

        /// <summary>
        /// Called when we get a touch-move event. We draw a line between the previous
        /// point for this source and the new point.
        /// </summary>
        private void onTouchMove(object sender, TouchArgs args)
        {
            // We get the previous point and draw a line to the current point...
            bool bGotPreviousPoint = m_mapPreviousPoints.ContainsKey(args.PointIndex);
            if (bGotPreviousPoint == false)
            {
                return;
            }
            Point previousPoint = m_mapPreviousPoints[args.PointIndex];

            // We get the touch position...
            Point clientPoint = args.ClientPosition;

            // We draw a line betweeb the two points in the color for this source...
            Pen pen = getPen(args.PointIndex);
            Graphics g = getGraphics();
            g.DrawLine(pen, previousPoint, clientPoint);

            // We store the new point...
            m_mapPreviousPoints[args.PointIndex] = clientPoint;
        }

        /// <summary>
        /// Returns the Graphics object used for drawing onto the screen.
        /// </summary>
        private Graphics getGraphics()
        {
            Graphics g = CreateGraphics();
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            return g;
        }

        /// <summary>
        /// We get a pen for the source-index passsed in. This lets us show multiple lines
        /// in a consistent color.
        /// </summary>
        private Pen getPen(int iPointIndex)
        {
            Color color;
            switch (iPointIndex)
            {
                case 0:
                    color = Color.Red;
                    break;

                case 1:
                    color = Color.Blue;
                    break;

                case 2:
                    color = Color.Green;
                    break;

                case 3:
                    color = Color.Yellow;
                    break;

                case 4:
                    color = Color.Orange;
                    break;

                default:
                    color = Color.Black;
                    break;
            }

            Pen pen = new Pen(color);
            pen.Width = 5;
            pen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
            pen.EndCap = System.Drawing.Drawing2D.LineCap.Round;

            return pen;
        }

        #endregion

        #region Private data

        // This object manages multi-touch events for this form...
        private MultiTouchInputClient m_MTIC = new MultiTouchInputClient();

        // Holds the previous values the positions for each source so 
        // that we can connect them with lines...
        private IDictionary<int, Point> m_mapPreviousPoints = new Dictionary<int, Point>();

        #endregion
    }
}
